package com.example.util;

import lombok.extern.slf4j.Slf4j;
import org.redisson.Redisson;
import org.redisson.api.RLock;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.concurrent.TimeUnit;

@Component
@Slf4j
public class RedisLockUtils {
    public static final String REPEAT_KEY = "yuan:repeat:";
    private static Redisson redisson;

    @Autowired
    public void setRedisson(Redisson redisson) {
        RedisLockUtils.redisson = redisson;
    }

    public static RLock getLock(String lockKey) {
        return redisson.getLock(lockKey);
    }

    /**
     * @param lock      锁对象
     * @param waitTime  获取锁等待时间
     * @param leaseTime 获取锁后保存时间
     * @return true/false
     */
    public static boolean tryLock(RLock lock, int waitTime, int leaseTime) {
        try {
            return RedisLockUtils.tryLock(lock, TimeUnit.SECONDS, waitTime, leaseTime);
        } catch (Exception e) {
            log.error("加锁失败！", e);
            return false;
        }
    }

    /**
     * @param lock      锁对象
     * @param timeUnit  时间单位
     * @param waitTime  获取锁等待时间
     * @param leaseTime 获取锁后保存时间
     * @return true/false
     */
    public static boolean tryLock(RLock lock, TimeUnit timeUnit, int waitTime, int leaseTime) {
        try {
            return lock.tryLock(waitTime, leaseTime, timeUnit);
        } catch (Exception e) {
            log.error("加锁失败！", e);
            return false;
        }
    }

    /**
     * 对锁的key添加系统标识前缀
     */
    public static String getLockKey(String key) {
        return RedisLockUtils.REPEAT_KEY + key;
    }

    /**
     * 释放锁
     * @param lockKey
     */
    public void unlock(String lockKey) {
        RLock lock = RedisLockUtils.getLock(lockKey);
        lock.unlock();
    }

    /**
     * 释放锁
     * @param lock
     */
    public void unlock(RLock lock) {
        lock.unlock();
    }

    /**
     * 带超时的锁
     * @param lockKey
     * @param timeout 超时时间   单位：秒
     */
    public static RLock lock(String lockKey, int timeout) {
        RLock lock = RedisLockUtils.getLock(lockKey);
        RedisLockUtils.lock(lockKey, TimeUnit.SECONDS,timeout);
        return lock;
    }

    /**
     * 带超时的锁
     * @param lockKey 锁
     * @param unit    时间单位
     * @param timeout 超时时间
     */
    public static RLock lock(String lockKey, TimeUnit unit, int timeout) {
        RLock lock = RedisLockUtils.getLock(lockKey);
        lock.lock(timeout, unit);
        return lock;
    }
}
